import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios"
import { ElMessage } from "element-plus"
import qs from 'qs'

// 返回异常状态码
export const statusCode = [
    { code: 1201, msg: '请先登录！' },
    { code: 1202, msg: '登录状态过期，请重新登录！' },
    { code: 1203, msg: '登录状态异常，请重新登录！' },
    { code: 1204, msg: '登录状态异常，请重新登录！' },
]

// 返回值类型
export interface Result<T = any> {
    code: number,
    msg: string,
    data?: T
}

class request {
    private instance: AxiosInstance

    // 初始化
    constructor(config: AxiosRequestConfig) {
        this.instance = axios.create(config)
        this.interceptors()
    }

    // 拦截器
    private interceptors() {
        // 请求拦截器
        this.instance.interceptors.request.use((config: AxiosRequestConfig) => {
            let token = localStorage.getItem('token')
            if (token) {
                config.headers = {
                    ...config.headers,
                    token: token
                }
            }
            return config
        }, (error: any) => {
            error.data = {}
            error.data.msg = '服务器异常，请联系管理员！'
            return error
        })

        // 响应拦截器
        this.instance.interceptors.response.use((res: AxiosResponse) => {
            if (res && res.data) {
                const data = res.data
                // 判断是否返回异常状态码
                for (let i in statusCode) {
                    if (statusCode[i].code == data.code) {
                        sessionStorage.clear()
                        localStorage.clear()
                        window.location.href = `/login?code=${data.code}`
                    }
                }
                // 返回1401 无访问权限
                if (data.code == 1401) {
                    ElMessage.error('你访问无权限')
                    setTimeout(() => {
                        window.location.href = '/home'
                    }, 2000)
                }
                // 返回2404 服务器异常
                if (data.code == 2404) {
                    ElMessage.error('服务器异常，请联系管理员！')
                }
                // 如果存在新的token 重置token
                if (data.new_token) {
                    localStorage.setItem('token', data.new_token)
                }
                return data
            }
        }, (error: any) => {
            error.data = {}
            if (error && error.response) {
                switch (error.response.status) {
                    case 400:
                        error.data.msg = '错误请求';
                        ElMessage.error(error.data.msg)
                        break
                    case 401:
                        error.data.msg = '未授权，请重新登录';
                        ElMessage.error(error.data.msg)
                        break
                    case 403:
                        error.data.msg = '拒绝访问';
                        ElMessage.error(error.data.msg)
                        break
                    case 404:
                        error.data.msg = '请求错误,未找到该资源';
                        ElMessage.error(error.data.msg)
                        break
                    case 405:
                        error.data.msg = '请求方法未允许';
                        ElMessage.error(error.data.msg)
                        break
                    case 408:
                        error.data.msg = '请求超时';
                        ElMessage.error(error.data.msg)
                        break
                    case 500:
                        error.data.msg = '服务器端出错';
                        ElMessage.error(error.data.msg)
                        break
                    case 501:
                        error.data.msg = '网络未实现';
                        ElMessage.error(error.data.msg)
                        break
                    case 502:
                        error.data.msg = '网络错误';
                        ElMessage.error(error.data.msg)
                        break
                    case 503:
                        error.data.msg = '服务不可用';
                        ElMessage.error(error.data.msg)
                        break
                    case 504:
                        error.data.msg = '网络超时';
                        ElMessage.error(error.data.msg)
                        break
                    case 505:
                        error.data.msg = 'http版本不支持该请求';
                        ElMessage.error(error.data.msg)
                        break
                    default:
                        error.data.msg = `连接错误${error.response.status}`;
                        ElMessage.error(error.data.msg)
                }
            } else {
                error.data.msg = "连接到服务器失败";
                ElMessage.error(error.data.msg)
            }
            return error
        })

    }

    // get请求 url?
    get<T = any>(url: string, parms?: any): Promise<Result<T>> {
        return new Promise((resolve, reject) => {
            this.instance.get<T>(url, {
                params: parms,
                paramsSerializer: (parms) => {
                    return qs.stringify(parms)
                },
            }).then((res) => {
                resolve(res as any)
            }).catch((error) => {
                reject(error)
            })
        })
    }

    // 提取字典中的值拼接成/val
    getParms(parms: any): string {
        let _params = "";
        if (Object.is(parms, undefined || null)) {
            _params = ''
        } else {
            for (const key in parms) {
                if (parms.hasOwnProperty(key) && parms[key]) {
                    _params += `${parms[key]}/`
                }
            }
        }
        return _params;
    }

    // get请求 url/val
    getRestApi<T = any>(url: string, id?: string | number): Promise<Result<T>> {
        return new Promise((resolve, reject) => {
            this.instance.get<T>(id ? `${url}${id}/` : url)
                .then((res) => {
                    resolve(res as any)
                }).catch((error) => {
                    reject(error)
                })
        })
    }

    // post请求
    post<T = any>(url: string, parms: any): Promise<Result<T>> {
        return new Promise((resolve, reject) => {
            this.instance.post<T>(url, parms, {
                transformRequest: [(params) => {
                    return JSON.stringify(params)
                }],
                headers: {
                    'Content-Type': 'application/json'
                }
            }).then((res) => {
                resolve(res as any)
            }).catch((error) => {
                reject(error)
            })
        })
    }

    // put请求
    put<T = any>(url: string, id: string | number, parms: any): Promise<Result<T>> {
        return new Promise((resolve, reject) => {
            this.instance.put<T>(`${url}${id}/`, parms, {
                transformRequest: [(params) => {
                    return JSON.stringify(params)
                }],
                headers: {
                    'Content-Type': 'application/json'
                }
            }).then((res) => {
                resolve(res as any)
            }).catch((error) => {
                reject(error)
            })
        })
    }

    // delete请求
    delete(url: string, id: string | number): Promise<Result> {
        return new Promise((resolve, reject) => {
            this.instance.delete(`${url}${id}/`)
                .then((res) => {
                    resolve(res as any)
                }).catch((error) => {
                    reject(error)
                })
        })
    }

}

export default request